Skip to content

Fix #11885: Disable ANSI colors when stdout is piped on JDK 22+#11887

Merged
gnodet merged 1 commit into
masterfrom
ci-issue-11885
May 19, 2026
Merged

Fix #11885: Disable ANSI colors when stdout is piped on JDK 22+#11887
gnodet merged 1 commit into
masterfrom
ci-issue-11885

Conversation

@gnodet
Copy link
Copy Markdown
Contributor

@gnodet gnodet commented Apr 3, 2026

Summary

  • Change ForcedSysOut to SysOut in JLine's TerminalBuilder configuration so that JLine properly checks whether stdout is a TTY before creating a system terminal
  • ForcedSysOut bypasses TTY detection, causing a non-dumb terminal to be created even when stdout is piped (because stdin is still a TTY), resulting in ANSI escape codes in piped output on JDK 22+ where the FFM provider creates a terminal from stdin alone

Root Cause

JLine's SystemOutput.ForcedSysOut always returns SystemStream.Output in select() without checking if stdout is actually a TTY. On JDK 21, the exec/JNI providers would fail to create a system terminal when stdout was piped, falling back to dumb. On JDK 22+ with the FFM provider, the terminal is created successfully (stdin is a TTY), producing a non-dumb terminal with colors enabled even when piped.

SystemOutput.SysOut does the right thing: it checks if stdout is a TTY first. If not, systemStream is null, and JLine falls back to a dumb terminal — exactly the correct behavior.

Test plan

  • mvn help:help -X | less should show plain text (no ANSI codes) on JDK 25+
  • mvn help:help -X > /tmp/out.txt should produce plain text on JDK 25+
  • mvn help:help -X should still show colored output on a real terminal
  • mvn --color=always help:help -X | less should still show ANSI codes (forced)
  • mvn --color=never help:help -X should show plain text
  • Behavior unchanged on JDK 17/21

Fixes #11885

Claude Code on behalf of Guillaume Nodet

🤖 Generated with Claude Code

… JDK 22+

Change ForcedSysOut to SysOut so that JLine properly checks whether
stdout is a TTY before creating a system terminal. ForcedSysOut
bypasses this check, which causes JLine to create a non-dumb terminal
even when stdout is piped (since stdin is still a TTY), resulting in
ANSI escape codes appearing in piped output on JDK 22+ where the FFM
provider successfully creates a terminal from stdin alone.

With SysOut, JLine detects that stdout is not a TTY and falls back to
a dumb terminal, correctly disabling ANSI colors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gnodet gnodet added this to the 4.0.0-rc-6 milestone Apr 3, 2026
@gnodet gnodet marked this pull request as draft April 3, 2026 20:32
Copy link
Copy Markdown
Member

@slawekjaranowski slawekjaranowski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test plan pass locally

@gnodet gnodet marked this pull request as ready for review May 19, 2026 15:25
@gnodet gnodet modified the milestones: 4.0.0-rc-6, 4.0.0 May 19, 2026
@gnodet gnodet merged commit ba9378d into master May 19, 2026
23 checks passed
@gnodet gnodet deleted the ci-issue-11885 branch May 19, 2026 15:25
@github-actions
Copy link
Copy Markdown

@gnodet Please assign appropriate label to PR according to the type of change.

gnodet added a commit to gnodet/maven that referenced this pull request May 19, 2026
…ted on JDK 22+ (apache#11887)

Change ForcedSysOut to SysOut so that JLine properly checks whether
stdout is a TTY before creating a system terminal. ForcedSysOut
bypasses this check, which causes JLine to create a non-dumb terminal
even when stdout is piped (since stdin is still a TTY), resulting in
ANSI escape codes appearing in piped output on JDK 22+ where the FFM
provider successfully creates a terminal from stdin alone.

With SysOut, JLine detects that stdout is not a TTY and falls back to
a dumb terminal, correctly disabling ANSI colors.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
gnodet added a commit that referenced this pull request May 19, 2026
… JDK 22+ (#11887) (#12111)

Change ForcedSysOut to SysOut so that JLine properly checks whether
stdout is a TTY before creating a system terminal. ForcedSysOut
bypasses this check, which causes JLine to create a non-dumb terminal
even when stdout is piped (since stdin is still a TTY), resulting in
ANSI escape codes appearing in piped output on JDK 22+ where the FFM
provider successfully creates a terminal from stdin alone.

With SysOut, JLine detects that stdout is not a TTY and falls back to
a dumb terminal, correctly disabling ANSI colors.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ANSI colors are not disabled in case of redirect to pipe or file on JDK25+

2 participants